﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Pavilion
{
    public class GameItemManager
    {
        private static GameItemManager instance;
        static public GameItemManager Instance { get { return (instance == null) ? new GameItemManager() : instance; } }

        public event Action<GameItem> GameItemAdded, GameItemRemoved;

        public bool DynamicallyCreateGameItems { get; set; }
        public GameItem this[string gameItemName] { get { return GetGameItem(gameItemName); } }
        public IEnumerable<GameItem> GameItemCollection { get { return gameItemDictionary.Values; } }
        public IEnumerable<string> GameItemNameCollection { get { return gameItemDictionary.Keys; } }

        private Dictionary<string, GameItem> gameItemDictionary;

        private GameItemManager()
        {
            instance = this;
            gameItemDictionary = new Dictionary<string, GameItem>();
        }

        public GameItem CreateGameItem(string gameItemName)
        {
            if (Contains(gameItemName))
                return gameItemDictionary[gameItemName];

            return AddGameItem(gameItemName);
        }

        private GameItem AddGameItem(string gameItemName)
        {
            GameItem gameItem = new GameItem(gameItemName);
            gameItem.Disposed += (x) => RemoveGameItem(x);
            gameItemDictionary.Add(gameItemName, gameItem);

            OnGameItemAdded(gameItem);

            return gameItem;
        }

        private void RemoveGameItem(GameItem gameItem)
        {
            if (gameItemDictionary.Remove(gameItem.Name))
                OnGameItemRemoved(gameItem);
        }

        public void UnloadAllGameItems()
        {
            while (gameItemDictionary.Count > 0)
                gameItemDictionary.Values.First().Dispose();
        }

        public void UnloadGameItem(string gameItemName)
        {
            gameItemDictionary[gameItemName].Dispose();
            //We remove it from the dictionary when the Disposed event of the gameItem fires.
        }

        public IEnumerable<T> GetToolsFromGameItems<T>() where T : GameToolBase
        {
            return GameItemCollection
                .Where((gameItem) => gameItem.ContainsTool<T>())
                .Select((gameItem) => gameItem.ObtainTool<T>());
        }

        public bool Contains(string gameItemName)
        {
            return gameItemDictionary.ContainsKey(gameItemName);
        }

        public GameItem GetGameItem(string gameItemName)
        {
            try { return gameItemDictionary[gameItemName]; }
            catch (Exception ex)
            {
                if (DynamicallyCreateGameItems)
                    return CreateGameItem(gameItemName);
                else
                    throw ex;
            }
        }

        private void OnGameItemAdded(GameItem gameItem)
        {
            if (GameItemAdded != null)
                GameItemAdded(gameItem);
        }

        private void OnGameItemRemoved(GameItem gameItem)
        {
            if (GameItemRemoved != null)
                GameItemRemoved(gameItem);
        }
    }
}
